package main;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class BaseRank {

	public abstract void rank();

	protected Map<String, Topic> topics = new HashMap<String, Topic>();

	/**
	 * read formatted-combined-txt file
	 * 
	 * @param filename
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	protected void readFormatted(String filename) throws FileNotFoundException, IOException {
		BufferedReader fmt_file = new BufferedReader(new FileReader(filename));
		for (String tmp = fmt_file.readLine(); tmp != null; tmp = fmt_file.readLine()) {
			String[] tmpArr = tmp.split(" ");
			if (tmpArr.length == 7) {
				Topic topic = topics.get(tmpArr[0]);
				if (topic == null) {
					topic = new Topic();
					topic.setId(tmpArr[0]);
					topics.put(topic.getId(), topic);
				}
				Passage psg = new Passage();
				psg.setTopicID(tmpArr[0]);
				psg.setDocumentID(tmpArr[1]);
				psg.setPassageID(tmpArr[2]);
				psg.setWeight(new BigDecimal(tmpArr[3]));
				psg.setStart(new Integer(tmpArr[4]));
				psg.setOffset(new Integer(tmpArr[5]));
				psg.setOutString(tmp);
				topic.addPassage(psg);
			} else {
				System.err.println(tmp);
			}
		}
		fmt_file.close();
	}

	/**
	 * read term-count-of-txts file
	 * 
	 * @param filename
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	protected void readTermCount(String filename) throws FileNotFoundException, IOException {
		BufferedReader top_file = new BufferedReader(new FileReader(filename));
		Topic topic = null;
		int counts = 0;
		int id = 0;
		Pattern p = Pattern.compile("passage #(\\d+): (\\d+) of the (\\d+) terms was found( >>|\\.)");
		for (String tmp = top_file.readLine(); tmp != null; tmp = top_file.readLine()) {
			if (tmp.startsWith("Topic#")) {
				String topicid = tmp.replaceFirst("Topic#", "").trim();
				topic = topics.get(topicid);
				if (topic == null) {
					topic = new Topic();
					topic.setId(topicid);
					topics.put(topicid, topic);
				}
				counts = 0;
				id = 0;
			} else if (tmp.startsWith("passage")) {
				if (topic != null) {
					Passage psg = (Passage) topic.getPassages().get(id);
					// Passage psg = new Passage();
					psg.setTopicID(topic.getId());
					Matcher m = p.matcher(tmp);
					StringBuffer sb = new StringBuffer();
					if (m.find()) {
						psg.setPassageID(m.group(1));
						psg.setTermsCount(m.group(2));
						psg.setTotalTermsCount(m.group(3));
						counts += Integer.parseInt(psg.getTermsCount());
						// System.out.println(psg.getPassageID());
						m.appendReplacement(sb, "");
						m.appendTail(sb);
					} else {
						System.err.println(tmp);
					}

					psg.setTerms(sb.toString().trim());
					psg.setFoundTerms(sb.toString().trim().split(" "));
					if (topic.getFullTermsCount() == 0) {
						topic.setFullTermsCount(Integer.valueOf(m.group(3)));
					}
					List<String> fullTerms = topic.getFullTerms();
					if (fullTerms.size() < topic.getFullTermsCount()) {
						for (int i = 0; i < psg.getFoundTerms().length; i++) {
							if (!fullTerms.contains(psg.getFoundTerms()[i])) {
								fullTerms.add(psg.getFoundTerms()[i]);
							}
						}
					}
//					topic.addPassage(psg);
					id++;
				}
			} else {
				topic.setTotalCount(counts);
				System.out.println(tmp);
			}
		}
		top_file.close();
	}

	/**
	 * is sorted array a same with sorted array b
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	protected boolean isContains(String[] a, Object[] b) {
		if (a == null && b == null)
			return true;
		if (a == null || b == null || a.length < b.length) {
			return false;
		}
		return Arrays.asList(a).containsAll(Arrays.asList(b));
	}

	protected class comEntry implements Comparator<Entry<String, Topic>> {

		public int compare(Entry<String, Topic> o1, Entry<String, Topic> o2) {
			if (o1 == null && o2 == null) {
				return 0;
			}
			return o1.getKey().compareTo(o2.getKey());
		}

	}

}
